#include "my_mqtt.h"
#include "my_common.h"
#include "my_nvs.h"
#include "my_ota.h"

#include "esp_log.h"
#include "mqtt_client.h"

static const char *TAG = "MQTT";
static char pub_topic[MQTT_TOPIC_LEN] = {0};
/**
 * MQTT事件回调函数
 */
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    esp_mqtt_event_handle_t event = event_data;
    esp_mqtt_client_handle_t client = event->client;

    switch ((esp_mqtt_event_id_t)event_id)
    {
    case MQTT_EVENT_CONNECTED: /* 连接到MQTT Broker */
        ESP_LOGI(TAG, "MQTT Start connect ...");
        char sub_topic[MQTT_TOPIC_LEN] = {0};
        if (is_mqtt_configured())
        {
            query_mqtt_sub_pub_topic(sub_topic, pub_topic);
        }
        else
        {
            query_mqtt_config_topic(sub_topic);
        }
        ESP_LOGI(TAG, "MQTT subscribe: %s", sub_topic);
        esp_mqtt_client_subscribe(client, sub_topic, 0);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("DATA=%.*s\r\n", event->data_len, event->data);

        if (strncmp(LIGHT_COMMAND_ON, event->data, strlen(LIGHT_COMMAND_ON)) == 0)
        {
            ESP_LOGI(TAG, "SET SWITCH ON");
            ESP_ERROR_CHECK(gpio_set_level(RELAY_PIN, 1));
            break;
        }

        if (strncmp(LIGHT_COMMAND_OFF, event->data, strlen(LIGHT_COMMAND_OFF)) == 0)
        {
            ESP_LOGI(TAG, "SET SWITCH OFF");
            ESP_ERROR_CHECK(gpio_set_level(RELAY_PIN, 0));
            break;
        }

        if (strncmp(LIGHT_COMMAND_REPORT, event->data, strlen(LIGHT_COMMAND_REPORT)) == 0)
        {

            int level = gpio_get_level(RELAY_PIN);
            printf("level:%d\r\n", level);

            if (level == 0)
            {
                esp_mqtt_client_publish(client, pub_topic, LIGHT_COMMAND_OFF, strlen(LIGHT_COMMAND_OFF), 0, 0);
            }
            else
            {
                esp_mqtt_client_publish(client, pub_topic, LIGHT_COMMAND_ON, strlen(LIGHT_COMMAND_ON), 0, 0);
            }

            ESP_LOGI(TAG, "publish: %s", pub_topic);
            break;
        }

        if (strncmp(LIGHT_COMMAND_CLEAR_CONFIG, event->data, strlen(LIGHT_COMMAND_CLEAR_CONFIG)) == 0)
        {
            ESP_LOGI(TAG, "Clear all config");
            clear_all_configured_flag();
            esp_restart();
            break;
        }
        // ota配置信息：<OTA,http://192.168.50.80/esp32c3-light.bin>
        if (strncmp(LIGHT_COMMAND_OTA, event->data, strlen(LIGHT_COMMAND_OTA)) == 0)
        {
            ESP_LOGI(TAG, "LIGHT_COMMAND_OTA");
            char *split = ",";
            strtok(event->data, split);
            char *uri = strtok(NULL, split);
            strtok(NULL, split);
            xTaskCreate(&ota_task, "ota_task", 8192, uri, 5, NULL);
            break;
        }

        // 接收配置信息，<topic,username,passwod,>
        // topic: <home/bedroom/mac_str/>
        if (strncmp(MQTT_CONFIG_TOPIC_PREFIX, event->topic, strlen(MQTT_CONFIG_TOPIC_PREFIX)) == 0)
        {
            ESP_LOGI(TAG, "Receive mqtt config: %s", event->data);
            char *split = ",";
            char *topic = strtok(event->data, split);
            char *username = strtok(NULL, split);
            char *password = strtok(NULL, split);
            strtok(NULL, split);
            printf("topic:%s, username:%s, password:%s\r\n", topic, username, password);

            persist_mqtt_topic_user_password(topic, username, password);

            ESP_LOGI(TAG, "Reboot");
            esp_restart();
        }
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        break;
    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT)
        {
            ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
        }
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
}

void mqtt_app_start()
{
    char mqtt_uri[MQTT_URI_LEN];
    query_mqtt_uri(mqtt_uri);
    ESP_LOGI(TAG, "MQTT URI:%s", mqtt_uri);

    esp_mqtt_client_config_t mqtt_cfg = {
        .broker.address.uri = mqtt_uri,
    };

    if (is_mqtt_configured())
    {
        char username[MQTT_USERNAME_LEN];
        char password[MQTT_PASSWORD_LEN];
        query_mqtt_username_password(username, password);
        mqtt_cfg.credentials.username = username;
        mqtt_cfg.credentials.authentication.password = password;
    }

    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    ESP_ERROR_CHECK(esp_mqtt_client_start(client));
}